﻿/*SOWY DateOperations class
 * Author:
 * Group: f10-2s
 * Version 0.01
 * This class is to process information received from the keywordProcessor class.
 * In this class, we know which tasks (CRUD) to do from the keywords received and also the type of tasks, (floating etc...)
 * However, this task mainly deal with date time 
 * e.g. of data received can be "ADD task1 during DateTime" This class would require to figure out which date the date is referring to.
 * Deal with CRUD keywords (Easy) and task type.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SOWY.common;

namespace SOWY
{
    class DataProcessing
    {
        private DateTime deadline;
        private DateTime startDate;
        private string crudType;
        private string dateTypeKeywords;
        private string task;
        private string date;
        private string specialKey;
        //need 2 enum type, one for CRUD one for tasktype

        public DataProcessing()
        {
            this.crudType = "";
            this.task = "";
            this.dateTypeKeywords = "";
            this.date = "";
        }
        public DataProcessing(string crudType, string task, string dateTypeKeywords, string date)
        {
            this.crudType = crudType.ToLower();
            this.task = task;
            this.dateTypeKeywords = dateTypeKeywords.ToLower();
            this.date = date;
        }

        public List<Task> processData(string crudType, string task, string dateTypeKeywords, string date)
        {
            DataOperations dataOperater = new DataOperations();
            assignVariables(crudType, task, dateTypeKeywords, date);

            //try process date first, if it pass, then format the task
            if (processTaskType())
            {
                task = formatTask();
                return dataOperater.toDatabase(crudType, task, startDate, deadline, specialKey, dateTypeKeywords);
            }
            else
            {
                List<Task> errorTask = new List<Task>();
                errorTask.Add(new Task(GeneralConstant.ERROR_INVALID_DATE, DateTime.MinValue, DateTime.MinValue, GeneralConstant.ERROR));
                return errorTask;
            }
        }

        private void assignVariables(string crudType, string task, string dateTypeKeywords, string date)
        {
            this.crudType = crudType.ToLower();
            this.task = task;
            this.dateTypeKeywords = dateTypeKeywords.ToLower();
            this.date = date;
        }
        private bool processTaskType()
        {
            switch (dateTypeKeywords)
            {
                case GeneralConstant.KEY_AFTER:   
                    return afterTask();

                case GeneralConstant.KEY_BEFORE: 
                    return beforeTask();

                case GeneralConstant.KEY_BETWEEN: 
                    return betweenTask();

                case GeneralConstant.KEY_ON:
                    return beforeTask();

                case GeneralConstant.KEY_FLOATING:
                    {
                        startDate = DateTime.MinValue;
                        deadline = DateTime.MinValue;
                        return true;
                    }

                default:
                    return false;
            }
        }

        private bool afterTask()
        {
            startDate = processDate(date);
            startDate = startDate.AddDays(1);
            return checkDate(startDate);
        }
        private bool beforeTask()
        {
            deadline = processDate(date);
            return checkDate(deadline);
        }
        private bool betweenTask()
        {
            DateTime[] processedDate = processTwoDate(this.date);
            startDate = processedDate[0];
            deadline = processedDate[1];
            return (checkDate(startDate) & checkDate(deadline));
        }
        private bool checkDate(DateTime startate)
        {
            if (startate.Year == 1)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
 
        private DateTime[] processTwoDate(string date)
        {
            string[] unformattedTime = seperateDates(date);
            DateTime[] dateTime = new DateTime[2];

            dateTime[0] = processDate(unformattedTime[0].Trim(), "start");
            dateTime[1] = processDate(unformattedTime[1].Trim(), "end", dateTime[0]);

            if (dateTime[0] < DateTime.Today)
                dateTime[0] = DateTime.Today;
            if (dateTime[1] < dateTime[0])
                dateTime[1] = dateTime[1].AddYears(1);

            return dateTime;
        }
        private string[] seperateDates(string date)
        {
            string[] unformattedTime = new string[2];
            string[] delimiter = { GeneralConstant.DELIMITER_TO, GeneralConstant.DELIMITER_AND };

            if (date.Length == 0)
            {
                unformattedTime[0] = "";
                unformattedTime[1] = "";
            }
            else
            {
                unformattedTime = date.ToLower().Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
                if (unformattedTime.Length == 1)
                {
                    unformattedTime = new string[2];
                    unformattedTime[0] = unformattedTime[1] = "";
                }
            }

            return unformattedTime;
        }

        private DateTime processDate(string date)
        {
            DateProcessor dp = new DateProcessor(date, dateTypeKeywords);
            return dp.processDate();
        }
        private DateTime processDate(string date, string startEnd)
        {
            DateProcessor dp = new DateProcessor(date, dateTypeKeywords, startEnd);
            return dp.processDate();
        }
        private DateTime processDate(string date, string startEnd, DateTime compare)
        {
            DateProcessor dp = new DateProcessor(date, dateTypeKeywords, startEnd, compare);
            return dp.processDate();
        }

        private string formatTask()
        {
            if (crudType.CompareTo("add") == 0)
            {
                return task;
            }
            else
            {
                TaskFormatter tf = new TaskFormatter(task);
                return tf.formatTask();
            }
        }
    }
}
